from abc import ABC, abstractmethod
from typing import Callable, Dict, List, Optional
import time
import logging
import threading
from datetime import datetime
from common.data_models import TickData, BarData, DataType

class BaseDataFeed(ABC):
    """行情数据基类 - 所有数据源必须实现此接口"""
    
    def __init__(self, config: Dict):
        self.config = config
        self.connected = False
        self.subscribed_symbols = set()
        self.tick_callbacks = []
        self.bar_callbacks = []
        self.logger = self._setup_logging()
        self._statistics = {
            'ticks_received': 0,
            'bars_received': 0,
            'errors': 0,
            'last_update': None
        }
        
    def _setup_logging(self):
        """设置日志"""
        logger = logging.getLogger(f"data_feed.{self.__class__.__name__}")
        if not logger.handlers:
            handler = logging.StreamHandler()
            formatter = logging.Formatter(
                '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
            )
            handler.setFormatter(formatter)
            logger.addHandler(handler)
            logger.setLevel(logging.INFO)
        return logger
        
    @abstractmethod
    def connect(self) -> bool:
        """连接数据源"""
        pass
        
    @abstractmethod
    def disconnect(self):
        """断开连接"""
        pass
        
    @abstractmethod
    def subscribe(self, symbols: List[str], data_type: DataType = DataType.TICK):
        """订阅行情数据"""
        pass
        
    @abstractmethod
    def unsubscribe(self, symbols: List[str], data_type: DataType = DataType.TICK):
        """取消订阅"""
        pass
        
    def add_tick_callback(self, callback: Callable[[TickData], None]):
        """添加Tick数据回调"""
        self.tick_callbacks.append(callback)
        self.logger.info(f"添加Tick回调，当前总数: {len(self.tick_callbacks)}")
        
    def add_bar_callback(self, callback: Callable[[BarData], None]):
        """添加K线数据回调"""
        self.bar_callbacks.append(callback)
        self.logger.info(f"添加Bar回调，当前总数: {len(self.bar_callbacks)}")
        
    def on_tick_data(self, tick: TickData):
        """处理Tick数据"""
        self._statistics['ticks_received'] += 1
        self._statistics['last_update'] = datetime.now()
        
        for callback in self.tick_callbacks:
            try:
                callback(tick)
            except Exception as e:
                self._statistics['errors'] += 1
                self.logger.error(f"Tick回调执行错误: {e}")
                
    def on_bar_data(self, bar: BarData):
        """处理K线数据"""
        self._statistics['bars_received'] += 1
        self._statistics['last_update'] = datetime.now()
        
        for callback in self.bar_callbacks:
            try:
                callback(bar)
            except Exception as e:
                self._statistics['errors'] += 1
                self.logger.error(f"Bar回调执行错误: {e}")
                
    def get_statistics(self) -> Dict:
        """获取统计信息"""
        return self._statistics.copy()
        
    def health_check(self) -> Dict[str, bool]:
        """健康检查"""
        now = datetime.now()
        last_update = self._statistics.get('last_update')
        
        is_healthy = (
            self.connected and 
            self._statistics['errors'] < 10 and
            (last_update is None or (now - last_update).total_seconds() < 60)
        )
        
        return {
            'connected': self.connected,
            'healthy': is_healthy,
            'subscribed_symbols_count': len(self.subscribed_symbols),
            'total_ticks': self._statistics['ticks_received'],
            'total_bars': self._statistics['bars_received'],
            'error_count': self._statistics['errors'],
            'last_data_time': last_update.isoformat() if last_update else None
        }